home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWorkshop / Source / Converters / PCX_SCRATCH / pcxread.m < prev    next >
Encoding:
Text File  |  1993-01-14  |  7.4 KB  |  330 lines

  1. /*
  2.  * pcxtoppm.c - Converts from a PC Paintbrush PCX file to a PPM file.
  3.  *
  4.  * Copyright (c) 1990 by Michael Davidson
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appear in all copies and that
  9.  * both that copyright notice and this permission notice appear in
  10.  * supporting documentation.
  11.  *
  12.  * This file is provided AS IS with no warranties of any kind.  The author
  13.  * shall have no liability with respect to the infringement of copyrights,
  14.  * trade secrets or any patents by this file or any part thereof.  In no
  15.  * event will the author be liable for any lost revenue or profits or
  16.  * other special, indirect and consequential damages.
  17.  *
  18.  */
  19.  
  20. #include    <stdio.h>
  21. #include <stdlib.h>
  22. #include <streams/streams.h>
  23. #include    "kludge.h"
  24. #include "pcxlib.h"
  25.  
  26. #define    PCX_MAGIC            0x0a        // PCX magic number
  27. #define    PCX_HDR_SIZE        128            // size of PCX header
  28. #define    PCX_256_COLORS    0x0c            // magic number for 256 colors
  29.  
  30. #define    MAXCOLORS       256
  31. #define    MAXPLANES    4
  32. #define    PCX_MAXVAL    255
  33.  
  34. static void read_pcx_image(    NXStream        *fp, 
  35.                         unsigned char     *buf, 
  36.                         int                 BytesPerLine, 
  37.                         int                 Planes, 
  38.                         int                 Height);
  39. static void pcx_planes_to_pixels(
  40.                         unsigned char        *pixels, 
  41.                         unsigned char     *bitplanes, 
  42.                         int                 bytesperline, 
  43.                         int                 planes, 
  44.                         int                 bitsperpixel);
  45. static void pcx_unpack_pixels( 
  46.                         unsigned char     *pixels, 
  47.                         unsigned char     *bitplanes, 
  48.                         int                 bytesperline, 
  49.                         int                 planes, 
  50.                         int                 bitsperpixel );
  51. static int GetByte(NXStream *fp);
  52. static int GetWord(NXStream *fp);
  53.  
  54. id pcxread(NXStream *ifp)
  55. {
  56.     register int        i;
  57.     int                Version;
  58.     int                Xmin, Ymin, Xmax, Ymax;
  59.     int                Width, Height;
  60.     register int        x, y;
  61.     int                Planes;
  62.     int                BitsPerPixel;
  63.     int                BytesPerLine;
  64.     unsigned char        Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
  65.     unsigned char        *pcximage;
  66.     unsigned char        *pcxplanes;
  67.     unsigned char        *pcxpixels;
  68.     id                pixels;
  69.     char                buffer[1024];
  70.  
  71. //    pcx_init(argc, argv);
  72.  
  73. //    ifp = pcx_openr(ifname);
  74.  
  75.     /*
  76.      * read the PCX header
  77.      */
  78.     if (GetByte(ifp) != PCX_MAGIC) {
  79.         pcx_error("Not a pcx file");
  80.     }
  81.  
  82.     Version    = GetByte(ifp);                // get version #
  83.     
  84.     if (GetByte(ifp) != 1) {                    // check for PCX run length encoding
  85.         pcx_error("Unknown encoding scheme in pcx file");
  86.     }
  87.  
  88.     BitsPerPixel= GetByte(ifp);
  89.     Xmin    = GetWord(ifp);
  90.     Ymin    = GetWord(ifp);
  91.     Xmax    = GetWord(ifp);
  92.     Ymax    = GetWord(ifp);
  93.  
  94.     Width    = (Xmax - Xmin) + 1;
  95.     Height    = (Ymax - Ymin) + 1;
  96.  
  97.     (void) GetWord(ifp);                    // ignore horizontal resolution
  98.     (void) GetWord(ifp);                    // ignore vertical resolution
  99.  
  100.      /*
  101.      * get the 16-color color map
  102.      */
  103.     for (i = 0; i < 16; i++) {
  104.         Red[i]    = GetByte(ifp);
  105.         Green[i]    = GetByte(ifp);
  106.         Blue[i]    = GetByte(ifp);
  107.     }
  108.  
  109.     (void) GetByte(ifp);                    // skip reserved byte
  110.     Planes    = GetByte(ifp);                // # of color planes
  111.     BytesPerLine= GetWord(ifp);            // # of bytes per line
  112.     (void) GetWord(ifp);                    // ignore palette info
  113.     
  114.     /*
  115.      * check that we can handle this image format
  116.      */
  117.     switch (BitsPerPixel)
  118.     {
  119.         case 1:
  120.         if (Planes > 4)
  121.             pcx_error("can't handle image with more than 4 planes");
  122.         break;
  123.  
  124.         case 2:
  125.         case 4:
  126.         case 8:
  127.             if (Planes == 1)
  128.                 break;
  129.         default:
  130.             sprintf(buffer, "can't handle %d bits per pixel image with %d planes",
  131.                                         BitsPerPixel,Planes);
  132.             pcx_error(buffer);
  133.     }
  134.  
  135.  
  136.     /*
  137.      * read the pcx format image
  138.      */
  139.     NXSeek(ifp, (long)PCX_HDR_SIZE, 0);
  140.     pcximage    = (unsigned char *)malloc(BytesPerLine * Planes * Height);
  141.     read_pcx_image(ifp, pcximage, BytesPerLine, Planes, Height);
  142.  
  143.     /*
  144.      * 256 color images have their color map at the end of the file
  145.      * preceeded by a magic byte
  146.      */
  147.     if (BitsPerPixel == 8) {
  148.         if (GetByte(ifp) != PCX_256_COLORS)
  149.             pcx_error("bad color map signature" );
  150.  
  151.         for (i = 0; i < MAXCOLORS; i++) {
  152.             Red[i]    = GetByte(ifp);
  153.             Green[i]    = GetByte(ifp);
  154.             Blue[i]    = GetByte(ifp);
  155.         }
  156.     }
  157.  
  158.     pixels    = pcx_allocarray(Width, Height);
  159.     pcxpixels    = (unsigned char *)malloc(Width+7);
  160.  
  161.     /*
  162.      * convert the image
  163.      */
  164.     for (y = 0; y < Height; y++) {
  165.         pcxplanes = pcximage + (y * BytesPerLine * Planes);
  166.  
  167.         if (Planes == 1) {
  168.             pcx_unpack_pixels(pcxpixels, pcxplanes,
  169.                                 BytesPerLine, Planes, BitsPerPixel);
  170.         } else {
  171.             pcx_planes_to_pixels(pcxpixels, pcxplanes,
  172.                                 BytesPerLine, Planes, BitsPerPixel);
  173.         }
  174.  
  175.         for (x = 0; x < Width; x++) {
  176.             i = pcxpixels[x];
  177.             PCX_ASSIGN(x, y, Red[i], Green[i], Blue[i]);
  178.         }
  179.     }
  180.  
  181.     pcx_close(ifp);
  182.     
  183.     return pixels;
  184. //    pcx_writeppm(stdout, pixels, Width, Height, (pixval) 255, 0 );
  185. }
  186.  
  187. static void read_pcx_image(    NXStream        *fp, 
  188.                         unsigned char     *buf, 
  189.                         int                 BytesPerLine, 
  190.                         int                 Planes, 
  191.                         int                 Height)
  192. {
  193.     int        c;
  194.     int        nbytes;
  195.     int        count;
  196.     char        buffer[1024];
  197.  
  198.     nbytes    = BytesPerLine * Planes * Height;
  199.  
  200.     while (nbytes > 0) {
  201.         c    = GetByte(fp);
  202.         if ((c & 0xc0) != 0xc0) {
  203.             *buf++    = c;
  204.             --nbytes;
  205.             continue;
  206.         }
  207.  
  208.         count    = c & 0x3f;
  209.         c    = GetByte(fp);
  210.         if (count > nbytes) {
  211.             sprintf(buffer, "repeat count spans end of image, count = %d, nbytes = %d",
  212.                                         count, nbytes);
  213.             pcx_error(buffer);
  214.         }
  215.  
  216.         nbytes    -= count;
  217.         while (--count >= 0)
  218.         *buf++ = c;
  219.     }
  220. }
  221.  
  222. /*
  223.  * convert multi-plane format into 1 pixel per byte
  224.  */
  225. static void pcx_planes_to_pixels(
  226.                         unsigned char        *pixels, 
  227.                         unsigned char     *bitplanes, 
  228.                         int                 bytesperline, 
  229.                         int                 planes, 
  230.                         int                 bitsperpixel)
  231. {
  232.     int                 i, j;
  233.     int                 npixels;
  234.     unsigned char        *p;
  235.  
  236.     if (planes > 4)
  237.         pcx_error("can't handle more than 4 planes" );
  238.     if (bitsperpixel != 1)
  239.         pcx_error("can't handle more than 1 bit per pixel" );
  240.  
  241.     /*
  242.      * clear the pixel buffer
  243.      */
  244.     npixels = (bytesperline * 8) / bitsperpixel;
  245.     p    = pixels;
  246.     while (--npixels >= 0)
  247.             *p++ = 0;
  248.  
  249.     /*
  250.      * do the format conversion
  251.      */
  252.     for (i = 0; i < planes; i++) {
  253.         int    pixbit, bits, mask;
  254.  
  255.         p    = pixels;
  256.         pixbit    = (1 << i);
  257.         for (j = 0; j < bytesperline; j++) {
  258.             bits = *bitplanes++;
  259.             for (mask = 0x80; mask != 0; mask >>= 1, p++)
  260.                 if (bits & mask)
  261.                     *p |= pixbit;
  262.         }
  263.     }
  264. }
  265.  
  266. /*
  267.  * convert packed pixel format into 1 pixel per byte
  268.  */
  269. static void pcx_unpack_pixels( 
  270.                         unsigned char     *pixels, 
  271.                         unsigned char     *bitplanes, 
  272.                         int                 bytesperline, 
  273.                         int                 planes, 
  274.                         int                 bitsperpixel )
  275. {
  276.     register int    bits;
  277.  
  278.     if (planes != 1)
  279.         pcx_error("can't handle packed pixels with more than 1 plane" );
  280.     if (bitsperpixel == 8) {
  281.         while (--bytesperline >= 0)
  282.             *pixels++ = *bitplanes++;
  283.     } else if (bitsperpixel == 4) {
  284.         while (--bytesperline >= 0) {
  285.             bits    = *bitplanes++;
  286.             *pixels++    = (bits >> 4) & 0x0f;
  287.             *pixels++    = (bits     ) & 0x0f;
  288.         }
  289.     } else if (bitsperpixel == 2) {
  290.         while (--bytesperline >= 0) {
  291.             bits    = *bitplanes++;
  292.             *pixels++    = (bits >> 6) & 0x03;
  293.             *pixels++    = (bits >> 4) & 0x03;
  294.             *pixels++    = (bits >> 2) & 0x03;
  295.             *pixels++    = (bits     ) & 0x03;
  296.         }
  297.     } else if (bitsperpixel == 1) {
  298.         while (--bytesperline >= 0) {
  299.             bits    = *bitplanes++;
  300.             *pixels++    = ((bits & 0x80) != 0);
  301.             *pixels++    = ((bits & 0x40) != 0);
  302.             *pixels++    = ((bits & 0x20) != 0);
  303.             *pixels++    = ((bits & 0x10) != 0);
  304.             *pixels++    = ((bits & 0x08) != 0);
  305.             *pixels++    = ((bits & 0x04) != 0);
  306.             *pixels++    = ((bits & 0x02) != 0);
  307.             *pixels++    = ((bits & 0x01) != 0);
  308.         }
  309.     }
  310. }
  311.  
  312. static int GetByte(NXStream *fp)
  313. {
  314.     int        c;
  315.  
  316.     if ((c = NXGetc(fp)) == EOF)
  317.         pcx_error("unexpected end of file" );
  318.  
  319.     return c;
  320. }
  321.  
  322. static int GetWord(NXStream *fp)
  323. {
  324.     int    c;
  325.  
  326.     c  = GetByte(fp);
  327.     c |= (GetByte(fp) << 8);
  328.     return c;
  329. }
  330.